#include "registerdialog.h"
#include "ui_registerdialog.h"
#include "global.h"
#include "httpmgr.h"

RegisterDialog::RegisterDialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::RegisterDialog),
    _countdown(5)
{
    ui->setupUi(this);
    ui->stackedWidget->setCurrentWidget(ui->page);
    //点击取消返回
    connect(ui->pushButton_register_cancel,
            &QPushButton::clicked,
            this,
            &RegisterDialog::back);
    //密码文本框
    ui->lineEdit_register_password->setEchoMode(QLineEdit::Password);
    ui->lineEdit_register_sure_password->setEchoMode(QLineEdit::Password);

    //为何符合qss的刷新逻辑，我们设置了state的两种状态
    ui->label_msg->setProperty("state","normal");
    //但是你设置了qt并不会马上刷新，你需要先刷新一下他的样式
    repolish(ui->label_msg);

    //连接注册模块的事件响应
    connect(HttpMgr::GetInstance().get(),
            &HttpMgr::sig_reg_mod_finish,
            this,&RegisterDialog::slot_reg_mod_finish);

    initHttpHandlers();

    //先清除所有错误提示
    ui->label_msg->clear();
    //为了保证注册所有的输入框都能在失去焦点后，立刻获得校验并且提示，我们连接
    //所有的输入和槽
    connect(ui->lineEdit_register_username,&QLineEdit::editingFinished,this,[this](){
        checkUserValid();
    });

    connect(ui->lineEdit_register_email, &QLineEdit::editingFinished, this, [this](){
        checkEmailValid();
    });

    connect(ui->lineEdit_register_password, &QLineEdit::editingFinished, this, [this](){
        checkPassValid();
    });

    connect(ui->lineEdit_register_sure_password, &QLineEdit::editingFinished, this, [this](){
        checkConfirmValid();
    });

    connect(ui->lineEdit_validte_code, &QLineEdit::editingFinished, this, [this](){
            checkVarifyValid();
    });

    //鼠标放上去变成小手

    ui->label_pass_visable->setCursor(Qt::PointingHandCursor);
    ui->label_confirm_pass_visable->setCursor(Qt::PointingHandCursor);
//    ui->label->setCursor(Qt::PointingHandCursor);
    //设置初始状态
    ui->label_pass_visable->SetState("unvisible","unvisible_hover","","visible",
                                "visible_hover","");

    ui->label_confirm_pass_visable->SetState("unvisible","unvisible_hover","","visible",
                                    "visible_hover","");
    //连接点击事件

    connect(ui->label_pass_visable, &ClickedLabel::clicked, this, [this]() {
        auto state = ui->label_pass_visable->GetCurState();
        if(state == ClickLbState::Normal){
            ui->lineEdit_register_password->setEchoMode(QLineEdit::Password);
        }else{
                ui->lineEdit_register_password->setEchoMode(QLineEdit::Normal);
        }
        qDebug() << "Label was clicked!";
    });

    connect(ui->label_confirm_pass_visable, &ClickedLabel::clicked, this, [this]() {
        auto state = ui->label_confirm_pass_visable->GetCurState();
        if(state == ClickLbState::Normal){
            ui->lineEdit_register_sure_password->setEchoMode(QLineEdit::Password);
        }else{
                ui->lineEdit_register_sure_password->setEchoMode(QLineEdit::Normal);
        }
        qDebug() << "Label was clicked!";
    });

    _countdown_timer = new QTimer(this);
    // 连接信号和槽
        connect(_countdown_timer, &QTimer::timeout, [this](){
            if(_countdown==0){
                _countdown_timer->stop();
                emit sigSwitchLogin();
                return;
            }
            _countdown--;
            auto str = QString("注册成功，%1 s后返回登录").arg(_countdown);
            ui->label_tip_lib->setText(str);
//            ui->->setText(str);
        });
}

RegisterDialog::~RegisterDialog()
{
    qDebug()<<"RegisterDialog已被析构";
    delete ui;
}

void RegisterDialog::showTip(const char* msg,bool error)
{

    ui->label_msg->setText(tr(msg));
    if(error){
        ui->label_msg->setProperty("state","normal");
    }else{
        ui->label_msg->setProperty("state","error");
    }
    repolish(ui->label_msg);

}

bool RegisterDialog::checkUserValid()
{
    if(ui->lineEdit_register_username->text() == ""){
        AddTipErr(TipErr::TIP_USER_ERR, tr("用户名不能为空"));
        return false;
    }

    DelTipErr(TipErr::TIP_USER_ERR);
    return true;
}

bool RegisterDialog::checkConfirmValid(){
    //对比下两个是否一样
    auto pass = ui->lineEdit_register_password->text();
    auto spass = ui->lineEdit_register_sure_password->text();
    if(pass != spass){
        //提示长度不准确
        AddTipErr(TipErr::TIP_CONFIRM_ERR, tr("两次密码不匹配"));
        return false;
    }
    DelTipErr(TipErr::TIP_CONFIRM_ERR);
    return true;
}
bool RegisterDialog::checkPassValid()
{
    auto pass = ui->lineEdit_register_password->text();

    if(pass.length() < 6 || pass.length()>15){
        //提示长度不准确
        AddTipErr(TipErr::TIP_PWD_ERR, tr("密码长度应为6~15"));
        return false;
    }

    // 创建一个正则表达式对象，按照上述密码要求
    // 这个正则表达式解释：
    // ^[a-zA-Z0-9!@#$%^&*]{6,15}$ 密码长度至少6，可以是字母、数字和特定的特殊字符
    QRegularExpression regExp("^[a-zA-Z0-9!@#$%^&*]{6,15}$");
    bool match = regExp.match(pass).hasMatch();
    if(!match){
        //提示字符非法
        AddTipErr(TipErr::TIP_PWD_ERR, tr("不能包含非法字符"));
        return false;;
    }

    DelTipErr(TipErr::TIP_PWD_ERR);

    return true;
}

void RegisterDialog::changeTipPage()
{
    _countdown_timer->stop();
    //切换页面
        ui->stackedWidget->setCurrentWidget(ui->page_2);

        // 启动定时器，设置间隔为1000毫秒（1秒）
        _countdown_timer->start(1000);
}



bool RegisterDialog::checkEmailValid()
{
    //验证邮箱的地址正则表达式
    auto email = ui->lineEdit_register_email->text();
    // 邮箱地址的正则表达式
    QRegularExpression regex(R"((\w+)(\.|_)?(\w*)@(\w+)(\.(\w+))+)");
    bool match = regex.match(email).hasMatch(); // 执行正则表达式匹配
    if(!match){
        //提示邮箱不正确
        AddTipErr(TipErr::TIP_EMAIL_ERR, tr("邮箱地址不正确"));
        return false;
    }

    DelTipErr(TipErr::TIP_EMAIL_ERR);
    return true;
}

bool RegisterDialog::checkVarifyValid()
{
    auto pass = ui->lineEdit_validte_code->text();
    if(pass.isEmpty()){
        AddTipErr(TipErr::TIP_VARIFY_ERR, tr("验证码不能为空"));
        return false;
    }

    DelTipErr(TipErr::TIP_VARIFY_ERR);
    return true;
}

void RegisterDialog::AddTipErr(TipErr te, QString tips)
{
    _tip_errs[te] = tips;
    QByteArray byteArray = tips.toUtf8();
        const char* cStr = byteArray.constData();
    showTip(cStr, false);
}

void RegisterDialog::DelTipErr(TipErr te)
{
    _tip_errs.remove(te);
    if(_tip_errs.empty()){
      ui->label_msg->clear();
      return;
    }
    QByteArray byteArray = _tip_errs.first().toUtf8();
    showTip(byteArray.constData(), false);
}

void RegisterDialog::initHttpHandlers()
{
    //注册获取验证码回包的逻辑
    _hanlders.insert(ReqId::ID_GET_VARIFY_CODE,
                     [this](const QJsonObject& ob){
        //转换成int方便操作
        int error = ob["error"].toInt();
        if(error!=ErrorCodes::SUCCESS){
            showTip("参数错误",false);
            return ;
        }

        auto email = ob["email"].toString();
        showTip("验证码已发送到邮箱，注意查收",true);
        qDebug() << "email is " << email;
    });

    //注册的回调
    _hanlders.insert(ReqId::ID_REG_USER, [this](QJsonObject jsonObj){
            int error = jsonObj["error"].toInt();
            if(error != ErrorCodes::SUCCESS){
                showTip("参数错误",false);
                return;
            }
            auto email = jsonObj["email"].toString();
            showTip("用户注册成功", true);
            qDebug()<< "email is " << email ;
            changeTipPage();
        });
}

void RegisterDialog::on_pushButton_get_validte_code_clicked()
{
    auto email = ui->lineEdit_register_email->text();
    QRegularExpression regex(R"([\w]+@[A-Za-z]+(\.[A-Za-z0-9]+){1,2})");
    if(regex.match(email).hasMatch()){
        //没有匹配就刷新
//        showTip("",true);
//        qDebug() << "发送邮箱";
        //发送http验证码
        QJsonObject json_obj;
        json_obj["email"] = email;
        HttpMgr::GetInstance()->PostHttpReq(QUrl(gate_url_prefix+"/get_varifycode"),
                            json_obj,
                            ReqId::ID_GET_VARIFY_CODE,
                            Modules::REGISTERMOD);

    }else{
        showTip("邮箱地址不正确",false);
    }
}

void RegisterDialog::slot_reg_mod_finish(ReqId id, QString res, ErrorCodes err)
{
    if(err!=ErrorCodes::SUCCESS){
        showTip("网络请求错误",false);
        return;
    }
    //解析json字符串，res转换成QByteArray，反序列化
    //document可以理解成json的文件
    QJsonDocument document =QJsonDocument::fromJson(res.toUtf8());
    if(document.isNull()){
        showTip("json解析失败",false);
        return;
    }
    //json解析错误
    if(!document.isObject()){
        //无法转换成json对象
        // 由于showTip是给用户看得，更详细的信息
        // 应该是系统日志的持有
        showTip("json解析失败",false);
        return;
    }
    //获得json对象，调用对应模块的方法
    _hanlders[id](document.object());
    return;
}

void RegisterDialog::on_pushButton_register_ok_clicked()
{
    if(ui->lineEdit_register_username->text() == ""){
            showTip("用户名不能为空", false);
            return;
        }

        if(ui->lineEdit_register_email->text() == ""){
            showTip("邮箱不能为空", false);
            return;
        }

        if(ui->lineEdit_register_password->text() == ""){
            showTip("密码不能为空", false);
            return;
        }

        if(ui->lineEdit_register_sure_password->text() == ""){
            showTip("确认密码不能为空", false);
            return;
        }

        if(ui->lineEdit_register_password->text() != ui->lineEdit_register_sure_password->text()){
            showTip("密码和确认密码不匹配", false);
            return;
        }

        if(ui->lineEdit_validte_code->text() == ""){
            showTip("验证码不能为空", false);
            return;
        }

        //day11 发送http请求注册用户
        QJsonObject json_obj;
        json_obj["user"] = ui->lineEdit_register_username->text();
        json_obj["email"] = ui->lineEdit_register_email->text();
        //简单加密
        json_obj["passwd"] = xorString(ui->lineEdit_register_password->text());
        json_obj["confirm"] = xorString(ui->lineEdit_register_sure_password->text());
        json_obj["varifycode"] = ui->lineEdit_validte_code->text();
        HttpMgr::GetInstance()->PostHttpReq(QUrl(gate_url_prefix+"/user_register"),
                     json_obj, ReqId::ID_REG_USER,Modules::REGISTERMOD);
}

void RegisterDialog::on_btn_return_login_clicked()
{
    _countdown_timer->stop();
    emit sigSwitchLogin();

}
